#pragma once
#include "GameplayEffectTypes.h"
#include "BaseAbilityTypes.generated.h"

class UGameplayEffect;

//伤害效果参数结构体，用于传递伤害能力效果的各种伤害和异常参数
USTRUCT(BlueprintType)
struct FDamageEffectParams
{
	GENERATED_BODY()
	FDamageEffectParams(){}

	//世界上下文对象
	UPROPERTY(BlueprintReadWrite)
	TObjectPtr<UObject> WorldContextObject = nullptr;
	//伤害游戏效果类
	UPROPERTY(BlueprintReadWrite)
	TSubclassOf<UGameplayEffect> DamageGameplayEffectClass = nullptr;
	//源能力系统组件
	UPROPERTY(BlueprintReadWrite)
	TObjectPtr<UAbilitySystemComponent> SourceAbilitySystemComponent;
	//目标能力系统组件
	UPROPERTY(BlueprintReadWrite)
	TObjectPtr<UAbilitySystemComponent> TargetAbilitySystemComponent;
	//伤害参数
	UPROPERTY(BlueprintReadWrite)
	float BaseDamage = 0.f;
	//能力等级
	UPROPERTY(BlueprintReadWrite)
	float AbilityLevel = 1.f;
	//伤害类型
	UPROPERTY(BlueprintReadWrite)
	FGameplayTag DamageType = FGameplayTag();
	//异常触发几率
	UPROPERTY(BlueprintReadWrite)
	float DebuffChance = 0.f;
	//异常伤害
	UPROPERTY(BlueprintReadWrite)
	float DebuffDamage = 0.f;
	//是否启用异常伤害 如果启用就按照伤害的百分比计算
	UPROPERTY(BlueprintReadWrite)
	bool DebuffDamagePercentage = false;
	//异常每跳频率
	UPROPERTY(BlueprintReadWrite)
	float DebuffFrequency = 0.f;
	//异常持续时间
	UPROPERTY(BlueprintReadWrite)
	float DebuffDuration = 0.f;
	//击杀敌人死亡时冲击量大小
	UPROPERTY(BlueprintReadWrite)
	float DeathImpulseMagnitude = 0.f;
	//击杀敌人死亡是冲击方向向量
	UPROPERTY(BlueprintReadWrite)
	FVector DeathImpulse = FVector::ZeroVector;
	//击退力度
	UPROPERTY(BlueprintReadWrite)
	float KnockbackForceMagnitude = 0.f;
	//击退触发几率
	UPROPERTY(BlueprintReadWrite)
	float KnockbackChance = 0.f;
	//击退方向
	UPROPERTY(BlueprintReadWrite)
	FVector KnockbackForce = FVector::ZeroVector;
	//硬直值
	UPROPERTY(BlueprintReadWrite)
	float Stagger = 0.f;
	//是否径向衰减伤害(也就是距离中心越远伤害越低)
	UPROPERTY(BlueprintReadWrite)
	bool bIsRadialDamage = false;
	//径向内半径
	UPROPERTY(BlueprintReadWrite)
	float RadialDamageInnerRadius = 0.f;
	//径向外半径
	UPROPERTY(BlueprintReadWrite)
	float RadialDamageOuterRadius = 0.f;
	//径向起源点
	UPROPERTY(BlueprintReadWrite)
	FVector RadialDamageOrigin = FVector::ZeroVector;
};

/*
 * 这个是用于自定义的GameplayEffectContext，继承原版的 然后拓展一些字段 解决原本的GameplayEffectContext不够用的问题
 * 增加比如 是否暴击 格挡 等等属性传递
 */
USTRUCT(BlueprintType)
struct FBaseGameplayEffectContext : public FGameplayEffectContext
{
	GENERATED_BODY()
public:
	/* 这部分是拓展的变量 start */
	bool IsBlockedHit() const { return bIsBlockedHit; } //是否格挡
	bool IsDodgeHit() const { return bIsDodgeHit; } //是否闪避
	bool IsAbsorbHit() const { return bIsAbsorbHit; } //是否吸收
	bool IsCriticalHit() const { return bIsCriticalHit; } //是否暴击
	bool IsStagger() const { return bIsStagger; } //是否硬直
	
	TSharedPtr<FGameplayTag> GetDamageType() const {return DamageType;} //获取伤害类型
	bool IsSuccessfulDebuff() const { return bIsSuccessfulDebuff; } //是否成功触发异常
	float GetDebuffDamage() const { return DebuffDamage; } //异常伤害
	float GetDebuffDuration() const { return DebuffDuration; } //异常持续时间
	float GetDebuffFrequency() const { return DebuffFrequency; } //异常每跳频率
	FVector GetDeathImpulse() const { return DeathImpulse; } //获取击杀敌人死亡是冲击方向向量
	FVector GetKnockbackForce() const { return KnockbackForce; } //获取击退方向向量
	float GetStagger() const { return Stagger; } //获取硬直值
	bool IsRadialDamage() const { return bIsRadialDamage; } //获取是否径向衰减伤害(也就是距离中心越远伤害越低)
	float GetRadialDamageInnerRadius() const { return RadialDamageInnerRadius; } //获取径向内半径
	float GetRadialDamageOuterRadius() const { return RadialDamageOuterRadius; } //获取径向外半径
	FVector GetRadialDamageOrigin() const { return RadialDamageOrigin; } //获取径向起源点
	
	
	

	void SetIsBlockedHit(bool bInIsBlockedHit) { bIsBlockedHit = bInIsBlockedHit; }
	void SetIsDodgeHit(bool bInIsDodgeHit) { bIsDodgeHit = bInIsDodgeHit; }
	void SetIsAbsorbHit(bool bInIsAbsorbHit) { bIsAbsorbHit = bInIsAbsorbHit; }
	void SetIsCriticalHit(bool bInIsCriticalHit) { bIsCriticalHit = bInIsCriticalHit; }
	void SetIsStagger(bool bInIsStagger) { bIsStagger = bInIsStagger; }
	void SetDamageType(TSharedPtr<FGameplayTag> InDamageType) { DamageType = InDamageType; }
	void SetIsSuccessfulDebuff(bool bInIsSuccessfulDebuff) { bIsSuccessfulDebuff = bInIsSuccessfulDebuff; }
	void SetDebuffDamage(float InDebuffDamage) { DebuffDamage = InDebuffDamage; }
	void SetDebuffDuration(float InDebuffDuration) { DebuffDuration = InDebuffDuration; }
	void SetDebuffFrequency(float InDebuffFrequency) { DebuffFrequency = InDebuffFrequency; }
	void SetDeathImpulse(const FVector& InDeathImpulse) { DeathImpulse = InDeathImpulse; }
	void SetKnockbackForce(const FVector& InForce) { KnockbackForce = InForce; }
	void SetStagger(float InStagger) { Stagger = InStagger; }
	void SetIsRadialDamage(bool bInIsRadialDamage) { bIsRadialDamage = bInIsRadialDamage; }
	void SetRadialDamageInnerRadius(float InRadialDamageInnerRadius) { RadialDamageInnerRadius = InRadialDamageInnerRadius; }
	void SetRadialDamageOuterRadius(float InRadialDamageOuterRadius) { RadialDamageOuterRadius = InRadialDamageOuterRadius; }
	void SetRadialDamageOrigin(const FVector& InRadialDamageOrigin) { RadialDamageOrigin = InRadialDamageOrigin; }
	
	
	/* 拓展结束 protected 中也要增加*/
	
	
	//重写这个获取脚本构造体函数，并且针对5.3进行了修改 去掉了StaticStruct的前缀
	/** Returns the actual struct used for serialization, subclasses must override this! */
	virtual UScriptStruct* GetScriptStruct() const
	{
		return StaticStruct();
	}
	//重写这个复制函数，并且针对5.3进行了修改 使用了 FBaseGameplayEffectContext
	/** Creates a copy of this context, used to duplicate for later modifications */
	virtual FBaseGameplayEffectContext* Duplicate() const
	{
		//创建一个新的GameplayEffectContext实例
		FBaseGameplayEffectContext* NewContext = new FBaseGameplayEffectContext();
		//复制当前对象的所有数据到新实例
		*NewContext = *this;
		//如果存在命中结果，进行深拷贝
		if (GetHitResult())
		{
			// Does a deep copy of the hit result
			//将命中结果深拷贝到新上下文中，避免共享指针问题
			NewContext->AddHitResult(*GetHitResult(), true);
		}
		//返回复制的新上下文
		return NewContext;
	}
	//重写这个序列化函数
	/** Custom serialization, subclasses must override this */
	virtual bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);

protected:
	//是否格挡伤害
	UPROPERTY()
	bool bIsBlockedHit = false;
	//是否闪避伤害
	UPROPERTY()
	bool bIsDodgeHit = false;
	//是否吸收伤害
	UPROPERTY()
	bool bIsAbsorbHit = false;
	//是否暴击
	UPROPERTY()
	bool bIsCriticalHit = false;
	//是否硬直
	UPROPERTY()
	bool bIsStagger = false;
	
	//伤害类型,TSharedPtr 是一个共享指针，不需要UPROPERTY属性 TSharedPtr他自己就可以内存管理
	TSharedPtr<FGameplayTag> DamageType;
	//是否成功触发debuff
	UPROPERTY()
	bool bIsSuccessfulDebuff = false;
	//异常伤害
	UPROPERTY()
	float DebuffDamage = 0.f;
	//异常持续时间
	UPROPERTY()
	float DebuffDuration = 0.f;
	//异常每跳频率
	UPROPERTY()
	float DebuffFrequency = 0.f;
	//击败敌人死亡时冲击向量
	UPROPERTY()
	FVector DeathImpulse = FVector::ZeroVector;
	//击退方向
	UPROPERTY()
	FVector KnockbackForce = FVector::ZeroVector;
	//硬直值
	UPROPERTY()
	float Stagger = 0.f;
	//是否径向衰减伤害(也就是距离中心越远伤害越低)
	UPROPERTY()
	bool bIsRadialDamage = false;
	//径向内半径
	UPROPERTY()
	float RadialDamageInnerRadius = 0.f;
	//径向外半径
	UPROPERTY()
	float RadialDamageOuterRadius = 0.f;
	//径向起源点
	UPROPERTY()
	FVector RadialDamageOrigin = FVector::ZeroVector;
	
};


//为FBaseGameplayEffectContext结构体定义类型特征
//这个模板特化告诉UE5如何处理这个结构体
template <>
struct TStructOpsTypeTraits<FBaseGameplayEffectContext> : public TStructOpsTypeTraitsBase2<FBaseGameplayEffectContext>
{
	enum
	{
		//启用网络序列化支持，允许结构体在网络间传输
		WithNetSerializer = true,
		//启用拷贝支持，允许结构体被复制
		WithCopy = true,
	};
};